3  scTCRseq: Define “Existing”, “Post-Nivolumab”, “Post-Vaccine” and vaccine-specifc clones in TILs and skin

3.1 Set up workspace

# Libraries
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.4     ✔ tidyr     1.3.1
✔ purrr     1.0.4     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(Seurat)
Loading required package: SeuratObject
Loading required package: sp

Attaching package: 'SeuratObject'

The following objects are masked from 'package:base':

    intersect, t
library(dplyr)
library(scRepertoire)

# Functions
#### Get frequency per clone across samples ------
get_clone_freq_across_samples <- function(tcr_list){
  all_freq.df <- data.frame(matrix(ncol = 2, nrow = 0))  
  # Rename columns so full_join works
  colnames(all_freq.df) <- c("beta", "vjaa")
  # Change type from logical to character so full_join works
  all_freq.df <- all_freq.df %>%
    mutate(beta = as.character(beta),
           vjaa = as.character(vjaa))
  # Loop across each timepoint/sample and get raw count and frequency of all clones
  for(i in c(1:length(tcr_list))){
    # Count number of cells per clone in this timepoint
    count_i <- tcr_list[[i]] %>%
      group_by(sample, beta, vjaa) %>%
      dplyr::count(sample, beta, vjaa)
    
    # Calculate total cells
    count_sum <- sum(count_i$n)
    
    # Divide cell count per clone by total number of cells for frequency (out of 100)
    freq_i <- count_i %>%
      rowwise() %>%
      mutate(freq = n/count_sum * 100) %>%
      ungroup() %>%
      dplyr::rename(!!paste0(names(tcr_list[i]), "_count") := "n",
                    !!paste0(names(tcr_list[i]), "_freq") := "freq") %>%
      select(-sample)
    
    # Append to dataframe holding frequencies and counts from all data
    all_freq.df <- full_join(all_freq.df, freq_i, by = c("beta", "vjaa"))
  }
  # Replace NAs with 0
  all_freq.df[is.na(all_freq.df)] <- 0
  
  return(all_freq.df)
}

### Get all barcodes per clone across all timepoints/samples
get_barcodes_per_clone <- function(tcr_list, all_freq.df){
  # For each clone, loop across each clone and pick up all barcodes across all timepoints with the clone
  # First concatenate barcode dataframes from all timepoints together
  all_barcodes.df <- do.call(rbind, tcr_list) %>%
    select(barcode, vjaa)
  # Create new dataframe to hold our clone-barcode mappings
  barcode_clone.df <- data.frame(matrix(ncol = 2, nrow = 0))
  # Now loop across all clones
  for(j in c(1:nrow(all_freq.df))){
    vjaa_j <- all_freq.df[j,"vjaa"]
    # pull barcodes with the clone
    barcodes_j <- all_barcodes.df %>%
      filter(vjaa == vjaa_j) %>%
      pull(barcode) %>%
      paste(collapse = ",")
    barcodes_vjaa_j <- c(barcodes_j, vjaa_j)
    barcode_clone.df <- rbind(barcode_clone.df, barcodes_vjaa_j)
  }
  # Rename the clone-barcode mapping dataframe
  colnames(barcode_clone.df) <- c("barcodes", "vjaa")
  
  return(barcode_clone.df)
}

#@Input: a list with multiple timepoints/samples as elements. Elements should be samples that you want to track clone frequencies across. 
#@Description: Wrangle dataframe so that each row is a clone, defined by vjaa, and the columns are the frequency and list of barcodes at each timepoint -----
track_chloetypes <- function(tcr_list){
  # Calculate the count and frequency of each clone across all samples
  all_freq.df <- get_clone_freq_across_samples(tcr_list)
  
  # Obtain the barcodes associated with each clone across all samples
  barcode_clone.df <- get_barcodes_per_clone(tcr_list, all_freq.df)
  
  if(nrow(all_freq.df) != nrow(barcode_clone.df)){stop("Missing clones somewhere")}
  
  # Join freq df and barcodes together
  freq_barcodes.df <- full_join(all_freq.df, barcode_clone.df, by = c("vjaa"))
  
  return(freq_barcodes.df)
}

3.2 Load experimentally tested reactive clones

experimental_file <- read.csv("/jsimonlab/users/chloetu/melanoma/Melanoma_Eryn/analysis_093024/Eryn_reactivity_results/reformatted_reconstructed_TCR_072324.csv") %>%
  mutate(vjaa = paste0(TRAV_1, ".", TRAJ_1, ";", CDR3A_1, "_", scTCR_TRBV_1, ".", TRBJ_1, ";", CDR3B_1))
 
# What are the possible answers
unique(experimental_file$Reactive)
[1] "No"  "Yes"
nonreactive_aa <- experimental_file %>%
  filter(Reactive == "No")

reactive_aa <- experimental_file %>%
  filter(Reactive == "Yes")

# Ensure there are 31 reactive TCRs in total
reactive_aa %>%
  dplyr::count(Patient)
  Patient  n
1     101  3
2     103  3
3     104 18
4     108  7

3.3 Load scRepertoire skin and tumor data with my custom vjaa column

combined_TCR <- readRDS("sctcr_scRep_combined_TCR_skin_tumor_Part1.Rds")

3.4 Format TCRs in TILs

3.4.1 Get frequencies of TILs in P101, P103, P104 and P108

# Obtain clonal frequencies and associated barcodes from P101 TIL samples
p101_tils_combined <- combined_TCR[c("P101_Tumor_W00","P101_Tumor_W12", "P101_Tumor_W20")]
p101_tils_freq <- track_chloetypes(p101_tils_combined)
# P103 TIL samples
p103_tils_combined <- combined_TCR[c("P103_Tumor_W00","P103_Tumor_W12", "P103_Tumor_W20")]
p103_tils_freq <- track_chloetypes(p103_tils_combined)
# P104 TIL samples
p104_tils_combined <- combined_TCR[c("P104_Tumor_PD")]
p104_tils_freq <- track_chloetypes(p104_tils_combined)
# P108 TIL samples
p108_tils_combined <- combined_TCR[c("P108_Tumor_PD")]
p108_tils_freq <- track_chloetypes(p108_tils_combined)

3.4.2 Categorize clones into groups (Existing, Post-Nivolumab, Post-Vaccine) and attach vaccine reactivity

Definitions- Existing clones: Seen the W00 timepoint Post-Nivolumab clones: Seen for the first time at the W12 timepoint Post-Nivolumab clones: Seen for the first time at the W20 timepoint

p101_tils_freq <- p101_tils_freq %>%
  mutate(sctcr_category = case_when(P101_Tumor_W00_freq > 0 ~ "Existing",
                                  P101_Tumor_W00_freq == 0 & P101_Tumor_W12_freq > 0 ~ "Post-Nivolumab",
                                  P101_Tumor_W00_freq == 0 & P101_Tumor_W12_freq == 0 & P101_Tumor_W20_freq > 0 ~ "Post-Vaccine"),
         sctcr_category2 = case_when(vjaa %in% reactive_aa$vjaa ~ "Reactive",
                                  P101_Tumor_W00_freq > 0 ~ "Existing",
                                  P101_Tumor_W00_freq == 0 & P101_Tumor_W12_freq > 0 ~ "Post-Nivolumab",
                                  P101_Tumor_W00_freq == 0 & P101_Tumor_W12_freq == 0 & P101_Tumor_W20_freq > 0 ~ "Post-Vaccine"),
         sctcr_category3 = case_when(vjaa %in% reactive_aa$vjaa ~ "Reactive",
                                   vjaa %in% nonreactive_aa$vjaa ~ "Tested, non-reactive",
                                  P101_Tumor_W00_freq > 0 ~ "Existing",
                                  P101_Tumor_W00_freq == 0 & P101_Tumor_W12_freq > 0 ~ "Post-Nivolumab",
                                  P101_Tumor_W00_freq == 0 & P101_Tumor_W12_freq == 0 & P101_Tumor_W20_freq > 0 ~ "Post-Vaccine"),
         reactive = case_when(vjaa %in% reactive_aa$vjaa ~ TRUE,
                              !(vjaa %in% reactive_aa$vjaa) ~ FALSE))

p103_tils_freq <- p103_tils_freq %>%
  mutate(sctcr_category = case_when(P103_Tumor_W00_freq > 0 ~ "Existing",
                                  P103_Tumor_W00_freq == 0 & P103_Tumor_W12_freq > 0 ~ "Post-Nivolumab",
                                  P103_Tumor_W00_freq == 0 & P103_Tumor_W12_freq == 0 & P103_Tumor_W20_freq > 0 ~ "Post-Vaccine"),
         sctcr_category2 = case_when(vjaa %in% reactive_aa$vjaa ~ "Reactive",
                                  P103_Tumor_W00_freq > 0 ~ "Existing",
                                  P103_Tumor_W00_freq == 0 & P103_Tumor_W12_freq > 0 ~ "Post-Nivolumab",
                                  P103_Tumor_W00_freq == 0 & P103_Tumor_W12_freq == 0 & P103_Tumor_W20_freq > 0 ~ "Post-Vaccine"),
         sctcr_category3 = case_when(vjaa %in% reactive_aa$vjaa ~ "Reactive",
                                   vjaa %in% nonreactive_aa$vjaa ~ "Tested, non-reactive",
                                  P103_Tumor_W00_freq > 0 ~ "Existing",
                                  P103_Tumor_W00_freq == 0 & P103_Tumor_W12_freq > 0 ~ "Post-Nivolumab",
                                  P103_Tumor_W00_freq == 0 & P103_Tumor_W12_freq == 0 & P103_Tumor_W20_freq > 0 ~ "Post-Vaccine"),
         reactive = case_when(vjaa %in% reactive_aa$vjaa ~ TRUE,
                              !(vjaa %in% reactive_aa$vjaa) ~ FALSE))

p104_tils_freq <- p104_tils_freq %>%
  filter(P104_Tumor_PD_freq > 0) %>%
  mutate(reactive = case_when(vjaa %in% reactive_aa$vjaa ~ TRUE,
                              !(vjaa %in% reactive_aa$vjaa) ~ FALSE))

p108_tils_freq <- p108_tils_freq %>%
  filter(P108_Tumor_PD_freq > 0) %>%
  mutate(reactive = case_when(vjaa %in% reactive_aa$vjaa ~ TRUE,
                              !(vjaa %in% reactive_aa$vjaa) ~ FALSE))

3.4.3 Count how many reactive clones there are in each patients TILs

p101_tils_freq %>%
  filter(reactive == TRUE)
                                beta
1       TRBV27.TRBJ2-1;CASSPTWGGSMVF
2 TRBV5-1.TRBJ2-7;CASSLGQGSIFSSYEQYF
3   TRBV7-2.TRBJ2-1;CASSLGSGVAYNEQFF
                                                         vjaa
1   TRAV21.TRAJ36;CAVRKQTGANNLFF_TRBV27.TRBJ2-1;CASSPTWGGSMVF
2 TRAV16.TRAJ28;CALGSYQLTF_TRBV5-1.TRBJ2-7;CASSLGQGSIFSSYEQYF
3 TRAV10.TRAJ27;CVVNTNAGKSTF_TRBV7-2.TRBJ2-1;CASSLGSGVAYNEQFF
  P101_Tumor_W00_count P101_Tumor_W00_freq P101_Tumor_W12_count
1                    0                   0                    0
2                    0                   0                    0
3                    0                   0                    0
  P101_Tumor_W12_freq P101_Tumor_W20_count P101_Tumor_W20_freq
1                   0                    1           0.3690037
2                   0                    1           0.3690037
3                   0                    1           0.3690037
                           barcodes sctcr_category sctcr_category2
1 P101_Tumor_W20_AAACCTGCACCGAAAG-1   Post-Vaccine        Reactive
2 P101_Tumor_W20_GCGACCACAGACAGGT-1   Post-Vaccine        Reactive
3 P101_Tumor_W20_TGGCGCAAGTGTGGCA-1   Post-Vaccine        Reactive
  sctcr_category3 reactive
1        Reactive     TRUE
2        Reactive     TRUE
3        Reactive     TRUE
p103_tils_freq %>%
  filter(reactive == TRUE)
                                beta
1 TRBV20-1.TRBJ2-2;CSARGRSGSGNTGELFF
2      TRBV20-1.TRBJ2-7;CSASEGAHEQYF
3    TRBV27.TRBJ1-1;CASSLGAAGLNTEAFF
                                                               vjaa
1 TRAV12-2.TRAJ32;CAFKAGGATNKLIF_TRBV20-1.TRBJ2-2;CSARGRSGSGNTGELFF
2         TRAV27.TRAJ22;CAVDSGSARQLTF_TRBV20-1.TRBJ2-7;CSASEGAHEQYF
3       TRAV8-3.TRAJ7;CAVGVEGNNRLAF_TRBV27.TRBJ1-1;CASSLGAAGLNTEAFF
  P103_Tumor_W00_count P103_Tumor_W00_freq P103_Tumor_W12_count
1                    0                   0                    0
2                    0                   0                    0
3                    0                   0                    0
  P103_Tumor_W12_freq P103_Tumor_W20_count P103_Tumor_W20_freq
1                   0                    1           0.0331565
2                   0                    6           0.1989390
3                   0                    3           0.0994695
                                                                                                                                                                                                     barcodes
1                                                                                                                                                                           P103_Tumor_W20_CGAGAAGCAAATACAG-1
2 P103_Tumor_W20_ATTGGACGTGTGTGCC-1,P103_Tumor_W20_CATCGGGCAGCATACT-1,P103_Tumor_W20_CTAGTGAAGACGACGT-1,P103_Tumor_W20_CTGCGGAAGTAGCGGT-1,P103_Tumor_W20_TGCTGCTCAGACGCCT-1,P103_Tumor_W20_TTATGCTCATCATCCC-1
3                                                                                                       P103_Tumor_W20_GAATGAATCGTCTGAA-1,P103_Tumor_W20_GCTCTGTAGTTACCCA-1,P103_Tumor_W20_TTCGGTCCACCTCGGA-1
  sctcr_category sctcr_category2 sctcr_category3 reactive
1   Post-Vaccine        Reactive        Reactive     TRUE
2   Post-Vaccine        Reactive        Reactive     TRUE
3   Post-Vaccine        Reactive        Reactive     TRUE
p104_tils_freq %>%
  filter(reactive == TRUE)
                                beta
1    TRBV10-3.TRBJ1-1;CAISGGAQVTEAFF
2  TRBV10-3.TRBJ2-2;CAIGPRKGGNTGELFF
3      TRBV18.TRBJ1-4;CASSPWGEGEKLFF
4     TRBV18.TRBJ2-2;CASSPTGENTGELFF
5         TRBV19.TRBJ2-1;CASTHYNEQFF
6       TRBV27.TRBJ2-5;CASSEGEEETQYF
7    TRBV4-1.TRBJ2-7;CASSRAGLYSYEQYF
8   TRBV5-1.TRBJ1-2;CASSLESGQEDYGYTF
9     TRBV5-1.TRBJ2-7;CASTSQDASYEQYF
10   TRBV5-4.TRBJ2-3;CASSRNQGSTDTQYF
11     TRBV5-5.TRBJ1-2;CASSTWTDYGYTF
12   TRBV5-5.TRBJ2-7;CASSLAGTYTYEQYF
13   TRBV5-5.TRBJ2-7;CASSLATSGSYEQYF
14    TRBV5-5.TRBJ2-7;CASSQAGGPYEQYF
15    TRBV6-1.TRBJ2-1;CASRVAGGPYEQFF
16     TRBV6-6.TRBJ1-1;CASSYGLNTEAFF
17    TRBV6-6.TRBJ2-7;CASQRLGQSYEQYF
18 TRBV7-8.TRBJ1-5;CASSLVFGTGSSQPQHF
                                                               vjaa
1        TRAV9-2.TRAJ30;CALSLDDKIIF_TRBV10-3.TRBJ1-1;CAISGGAQVTEAFF
2  TRAV41.TRAJ22;CAVLLISSGSARQLTF_TRBV10-3.TRBJ2-2;CAIGPRKGGNTGELFF
3      TRAV29DV5.TRAJ40;CAASATGTYKYIF_TRBV18.TRBJ1-4;CASSPWGEGEKLFF
4     TRAV29DV5.TRAJ29;CAASGTGNTPLVF_TRBV18.TRBJ2-2;CASSPTGENTGELFF
5            TRAV27.TRAJ31;CAGEKSNNARLMF_TRBV19.TRBJ2-1;CASTHYNEQFF
6         TRAV17.TRAJ12;CATVRMDSSYKLIF_TRBV27.TRBJ2-5;CASSEGEEETQYF
7          TRAV21.TRAJ34;CAPNTDKLIF_TRBV4-1.TRBJ2-7;CASSRAGLYSYEQYF
8   TRAV26-1.TRAJ23;CIGVLYNQGGKLIF_TRBV5-1.TRBJ1-2;CASSLESGQEDYGYTF
9        TRAV13-1.TRAJ33;CAAGSNYQLIW_TRBV5-1.TRBJ2-7;CASTSQDASYEQYF
10  TRAV12-3.TRAJ42;CAMSSVGGSQGNLIF_TRBV5-4.TRBJ2-3;CASSRNQGSTDTQYF
11      TRAV9-2.TRAJ58;CALIEETSGSRLTF_TRBV5-5.TRBJ1-2;CASSTWTDYGYTF
12     TRAV21.TRAJ58;CAVREETSGSRLTF_TRBV5-5.TRBJ2-7;CASSLAGTYTYEQYF
13     TRAV8-6.TRAJ43;CAVSEINNNDMRF_TRBV5-5.TRBJ2-7;CASSLATSGSYEQYF
14      TRAV8-6.TRAJ8;CAVSDSTGFQKLVF_TRBV5-5.TRBJ2-7;CASSQAGGPYEQYF
15       TRAV8-6.TRAJ43;CAVRDNNNDMRF_TRBV6-1.TRBJ2-1;CASRVAGGPYEQFF
16      TRAV13-2.TRAJ37;CAESLSNTGKLIF_TRBV6-6.TRBJ1-1;CASSYGLNTEAFF
17 TRAV38-2DV8.TRAJ54;CAYRSEQGAQKLVF_TRBV6-6.TRBJ2-7;CASQRLGQSYEQYF
18 TRAV38-2DV8.TRAJ43;CAYRIHNDMRF_TRBV7-8.TRBJ1-5;CASSLVFGTGSSQPQHF
   P104_Tumor_PD_count P104_Tumor_PD_freq
1                    1         0.05817336
2                    2         0.11634671
3                    1         0.05817336
4                    2         0.11634671
5                    1         0.05817336
6                    1         0.05817336
7                    2         0.11634671
8                    3         0.17452007
9                    3         0.17452007
10                   1         0.05817336
11                   1         0.05817336
12                   4         0.23269343
13                   2         0.11634671
14                   2         0.11634671
15                   3         0.17452007
16                   1         0.05817336
17                   1         0.05817336
18                   2         0.11634671
                                                                                                                              barcodes
1                                                                                                     P104_Tumor_PD_GGACAGAGTTGTGGAG-1
2                                                                    P104_Tumor_PD_GATCGTAAGCGACGTA-1,P104_Tumor_PD_TCATTACAGCTCCTTC-1
3                                                                                                     P104_Tumor_PD_TACACGAAGCGTTTAC-1
4                                                                    P104_Tumor_PD_ACCGTAAAGGCTCTTA-1,P104_Tumor_PD_TCTTTCCAGCCAGTAG-1
5                                                                                                     P104_Tumor_PD_TGCCCATCACTGTTAG-1
6                                                                                                     P104_Tumor_PD_GAGTCCGTCCTTTACA-1
7                                                                    P104_Tumor_PD_CATATTCTCTAACTTC-1,P104_Tumor_PD_GTTCGGGCACTTAACG-1
8                                   P104_Tumor_PD_CATCGAAGTGTGCGTC-1,P104_Tumor_PD_GCGGGTTTCGCCAGCA-1,P104_Tumor_PD_TCGCGAGCAATGTAAG-1
9                                   P104_Tumor_PD_AGCTTGACAGCCACCA-1,P104_Tumor_PD_CACACTCTCGGCGCTA-1,P104_Tumor_PD_GCCTCTATCGAGGTAG-1
10                                                                                                    P104_Tumor_PD_CAAGTTGTCAATCACG-1
11                                                                                                    P104_Tumor_PD_ACACCGGAGCCGCCTA-1
12 P104_Tumor_PD_CTACATTTCAGTCCCT-1,P104_Tumor_PD_CTAGAGTGTTGTCGCG-1,P104_Tumor_PD_TCCACACGTAAGTGGC-1,P104_Tumor_PD_TGACGGCAGCCTTGAT-1
13                                                                   P104_Tumor_PD_CTCGTACCACATAACC-1,P104_Tumor_PD_GTGCTTCAGGTCATCT-1
14                                                                   P104_Tumor_PD_CTCTGGTTCCCAACGG-1,P104_Tumor_PD_GATGCTAGTTTGTTGG-1
15                                  P104_Tumor_PD_ACATGGTTCACGAAGG-1,P104_Tumor_PD_ATTCTACTCAGCTTAG-1,P104_Tumor_PD_CATATTCGTCCTCCAT-1
16                                                                                                    P104_Tumor_PD_TACAGTGGTCGCTTCT-1
17                                                                                                    P104_Tumor_PD_GCATGCGCACCCTATC-1
18                                                                   P104_Tumor_PD_AGTTGGTCAATGACCT-1,P104_Tumor_PD_CATCGAAGTAGGACAC-1
   reactive
1      TRUE
2      TRUE
3      TRUE
4      TRUE
5      TRUE
6      TRUE
7      TRUE
8      TRUE
9      TRUE
10     TRUE
11     TRUE
12     TRUE
13     TRUE
14     TRUE
15     TRUE
16     TRUE
17     TRUE
18     TRUE
p108_tils_freq %>%
  filter(reactive == TRUE)
                              beta
1  TRBV11-2.TRBJ2-7;CASSRTSGTYEQYF
2   TRBV19.TRBJ2-5;CASSMGPGGAETQYF
3   TRBV2.TRBJ2-2;CASSDPSGALTGELFF
4  TRBV20-1.TRBJ2-1;CSAETGDYYNEQFF
5  TRBV29-1.TRBJ1-3;CSVIGTASGNTIYF
6 TRBV6-6.TRBJ1-2;CASSYSTRDTNYGYTF
7    TRBV7-6.TRBJ2-1;CASSQGLRNEQFF
                                                             vjaa
1  TRAV8-6.TRAJ11;CAVSEMNSGYSTLTF_TRBV11-2.TRBJ2-7;CASSRTSGTYEQYF
2     TRAV1-1.TRAJ3;CAVPGGGSASKIIF_TRBV19.TRBJ2-5;CASSMGPGGAETQYF
3      TRAV8-6.TRAJ4;CAVRAGGYNKLIF_TRBV2.TRBJ2-2;CASSDPSGALTGELFF
4     TRAV3.TRAJ34;CAVRDILNTDKLIF_TRBV20-1.TRBJ2-1;CSAETGDYYNEQFF
5  TRAV12-1.TRAJ13;CVVAFGGGYQKVTF_TRBV29-1.TRBJ1-3;CSVIGTASGNTIYF
6 TRAV38-1.TRAJ31;CAFMKQRNNARLMF_TRBV6-6.TRBJ1-2;CASSYSTRDTNYGYTF
7    TRAV12-2.TRAJ22;CAVVRSGSARQLTF_TRBV7-6.TRBJ2-1;CASSQGLRNEQFF
  P108_Tumor_PD_count P108_Tumor_PD_freq                         barcodes
1                   1          0.0965251 P108_Tumor_PD_TGAGCCGAGAATGTTG-1
2                   1          0.0965251 P108_Tumor_PD_ACTTGTTCAGTCAGAG-1
3                   1          0.0965251 P108_Tumor_PD_TACTCGCAGACAGAGA-1
4                   1          0.0965251 P108_Tumor_PD_GGAAAGCGTCTCATCC-1
5                   1          0.0965251 P108_Tumor_PD_CTTACCGAGGCGATAC-1
6                   1          0.0965251 P108_Tumor_PD_TTTGCGCAGCTAGCCC-1
7                   1          0.0965251 P108_Tumor_PD_ACGGGTCCATAGAAAC-1
  reactive
1     TRUE
2     TRUE
3     TRUE
4     TRUE
5     TRUE
6     TRUE
7     TRUE

3.5 Format skin

3.5.1 Get frequencies of clones in skin in P101, P103, P104 and P108

# Obtain clonal frequencies and associated barcodes from P101 skin samples
p101_skin_combined <- combined_TCR[c("P101_Skin_Pre3rd", "P101_Skin_Post3rd")]
p101_skin_freq <- track_chloetypes(p101_skin_combined)
# P103 skin samples
p103_skin_combined <- combined_TCR[c("P103_Skin_Pre3rd", "P103_Skin_Post3rd")]
p103_skin_freq <- track_chloetypes(p103_skin_combined)
# P104 skin samples
p104_skin_combined <- combined_TCR[c("P104_Skin_Pre3rd", "P104_Skin_Post3rd")]
p104_skin_freq <- track_chloetypes(p104_skin_combined)
# P105 skin samples
p105_skin_combined <- combined_TCR[c("P105_Skin_Pre3rd", "P105_Skin_Post3rd")]
p105_skin_freq <- track_chloetypes(p105_skin_combined)
# P105 skin samples
p106_skin_combined <- combined_TCR[c("P106_Skin_Pre3rd", "P106_Skin_Post3rd")]
p106_skin_freq <- track_chloetypes(p106_skin_combined)
# P108 skin samples
p108_skin_combined <- combined_TCR[c("P108_Skin_Pre3rd", "P108_Skin_Post3rd")]
p108_skin_freq <- track_chloetypes(p108_skin_combined)
# P109 skin samples
p109_skin_combined <- combined_TCR[c("P109_Skin_Pre3rd")]
p109_skin_freq <- track_chloetypes(p109_skin_combined)
# P110 skin samples
p110_skin_combined <- combined_TCR[c("P110_Skin_Pre3rd", "P110_Skin_Post3rd")]
p110_skin_freq <- track_chloetypes(p110_skin_combined)
# P111 skin samples
p111_skin_combined <- combined_TCR[c("P111_Skin_Pre3rd", "P111_Skin_Post3rd")]
p111_skin_freq <- track_chloetypes(p111_skin_combined)

3.5.2 Categorize clones into groups (Existing, Post-Nivolumab, Post-Vaccine) and attach vaccine reactivity

Definitions- Existing clones: Seen the W00 timepoint Post-Nivolumab clones: Seen for the first time at the W12 timepoint Post-Nivolumab clones: Seen for the first time at the W20 timepoint

p101_skin_freq <- p101_skin_freq %>%
  mutate(sctcr_category = case_when(P101_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P101_Skin_Pre3rd_freq == 0 & P101_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category2 = case_when(vjaa %in% reactive_aa$vjaa ~ "Reactive",
                                  P101_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P101_Skin_Pre3rd_freq == 0 & P101_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category3 = case_when(vjaa %in% reactive_aa$vjaa ~ "Reactive",
                                   vjaa %in% nonreactive_aa$vjaa ~ "Tested, non-reactive",
                                  P101_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P101_Skin_Pre3rd_freq == 0 & P101_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         reactive = case_when(vjaa %in% reactive_aa$vjaa ~ TRUE,
                              !(vjaa %in% reactive_aa$vjaa) ~ FALSE))

p103_skin_freq <- p103_skin_freq %>%
  mutate(sctcr_category = case_when(P103_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P103_Skin_Pre3rd_freq == 0 & P103_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category2 = case_when(vjaa %in% reactive_aa$vjaa ~ "Reactive",
                                  P103_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P103_Skin_Pre3rd_freq == 0 & P103_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category3 = case_when(vjaa %in% reactive_aa$vjaa ~ "Reactive",
                                   vjaa %in% nonreactive_aa$vjaa ~ "Tested, non-reactive",
                                  P103_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P103_Skin_Pre3rd_freq == 0 & P103_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         reactive = case_when(vjaa %in% reactive_aa$vjaa ~ TRUE,
                              !(vjaa %in% reactive_aa$vjaa) ~ FALSE))

p104_skin_freq <- p104_skin_freq %>%
  mutate(sctcr_category = case_when(P104_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P104_Skin_Pre3rd_freq == 0 & P104_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category2 = case_when(vjaa %in% reactive_aa$vjaa ~ "Reactive",
                                  P104_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P104_Skin_Pre3rd_freq == 0 & P104_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category3 = case_when(vjaa %in% reactive_aa$vjaa ~ "Reactive",
                                   vjaa %in% nonreactive_aa$vjaa ~ "Tested, non-reactive",
                                  P104_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P104_Skin_Pre3rd_freq == 0 & P104_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         reactive = case_when(vjaa %in% reactive_aa$vjaa ~ TRUE,
                              !(vjaa %in% reactive_aa$vjaa) ~ FALSE))

p105_skin_freq <- p105_skin_freq %>%
  mutate(sctcr_category = case_when(P105_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P105_Skin_Pre3rd_freq == 0 & P105_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category2 = case_when(P105_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P105_Skin_Pre3rd_freq == 0 & P105_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category3 = case_when(P105_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P105_Skin_Pre3rd_freq == 0 & P105_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         reactive = FALSE)

p106_skin_freq <- p106_skin_freq %>%
  mutate(sctcr_category = case_when(P106_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P106_Skin_Pre3rd_freq == 0 & P106_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category2 = case_when(P106_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P106_Skin_Pre3rd_freq == 0 & P106_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category3 = case_when(P106_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P106_Skin_Pre3rd_freq == 0 & P106_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         reactive = FALSE)

p108_skin_freq <- p108_skin_freq %>%
  mutate(sctcr_category = case_when(P108_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P108_Skin_Pre3rd_freq == 0 & P108_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category2 = case_when(vjaa %in% reactive_aa$vjaa ~ "Reactive",
                                  P108_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P108_Skin_Pre3rd_freq == 0 & P108_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category3 = case_when(vjaa %in% reactive_aa$vjaa ~ "Reactive",
                                   vjaa %in% nonreactive_aa$vjaa ~ "Tested, non-reactive",
                                  P108_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P108_Skin_Pre3rd_freq == 0 & P108_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         reactive = case_when(vjaa %in% reactive_aa$vjaa ~ TRUE,
                              !(vjaa %in% reactive_aa$vjaa) ~ FALSE))

p109_skin_freq <- p109_skin_freq %>%
  mutate(sctcr_category = case_when(P109_Skin_Pre3rd_freq > 0 ~ "Pre3rd"),
         sctcr_category2 = case_when(P109_Skin_Pre3rd_freq > 0 ~ "Pre3rd"),
         sctcr_category3 = case_when(P109_Skin_Pre3rd_freq > 0 ~ "Pre3rd"),
         reactive = FALSE)

p110_skin_freq <- p110_skin_freq %>%
  mutate(sctcr_category = case_when(P110_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P110_Skin_Pre3rd_freq == 0 & P110_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category2 = case_when(P110_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P110_Skin_Pre3rd_freq == 0 & P110_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category3 = case_when(P110_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P110_Skin_Pre3rd_freq == 0 & P110_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         reactive = FALSE)

p111_skin_freq <- p111_skin_freq %>%
  mutate(sctcr_category = case_when(P111_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P111_Skin_Pre3rd_freq == 0 & P111_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category2 = case_when(P111_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P111_Skin_Pre3rd_freq == 0 & P111_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         sctcr_category3 = case_when(P111_Skin_Pre3rd_freq > 0 ~ "Pre3rd",
                                  P111_Skin_Pre3rd_freq == 0 & P111_Skin_Post3rd_freq > 0 ~ "Post3rd"),
         reactive = FALSE)

3.5.3 Count how many reactive clones there are in each sample

p101_skin_freq %>%
  filter(reactive == TRUE)
                              beta
1     TRBV27.TRBJ2-1;CASSPTWGGSMVF
2 TRBV7-2.TRBJ2-1;CASSLGSGVAYNEQFF
                                                         vjaa
1   TRAV21.TRAJ36;CAVRKQTGANNLFF_TRBV27.TRBJ2-1;CASSPTWGGSMVF
2 TRAV10.TRAJ27;CVVNTNAGKSTF_TRBV7-2.TRBJ2-1;CASSLGSGVAYNEQFF
  P101_Skin_Pre3rd_count P101_Skin_Pre3rd_freq P101_Skin_Post3rd_count
1                      1             0.3401361                       0
2                      1             0.3401361                       0
  P101_Skin_Post3rd_freq                            barcodes sctcr_category
1                      0 P101_Skin_Pre3rd_AACTGGTAGGCTAGGT-1         Pre3rd
2                      0 P101_Skin_Pre3rd_GGGATGACACTGAAGG-1         Pre3rd
  sctcr_category2 sctcr_category3 reactive
1        Reactive        Reactive     TRUE
2        Reactive        Reactive     TRUE
p103_skin_freq %>%
  filter(reactive == TRUE)
 [1] beta                    vjaa                    P103_Skin_Pre3rd_count 
 [4] P103_Skin_Pre3rd_freq   P103_Skin_Post3rd_count P103_Skin_Post3rd_freq 
 [7] barcodes                sctcr_category          sctcr_category2        
[10] sctcr_category3         reactive               
<0 rows> (or 0-length row.names)
p104_skin_freq %>%
  filter(reactive == TRUE)
                            beta
1 TRBV5-1.TRBJ2-7;CASTSQDASYEQYF
2  TRBV5-5.TRBJ1-2;CASSTWTDYGYTF
3 TRBV5-5.TRBJ2-7;CASSQAGGPYEQYF
                                                         vjaa
1  TRAV13-1.TRAJ33;CAAGSNYQLIW_TRBV5-1.TRBJ2-7;CASTSQDASYEQYF
2 TRAV9-2.TRAJ58;CALIEETSGSRLTF_TRBV5-5.TRBJ1-2;CASSTWTDYGYTF
3 TRAV8-6.TRAJ8;CAVSDSTGFQKLVF_TRBV5-5.TRBJ2-7;CASSQAGGPYEQYF
  P104_Skin_Pre3rd_count P104_Skin_Pre3rd_freq P104_Skin_Post3rd_count
1                      0                     0                       1
2                      0                     0                       1
3                      0                     0                       1
  P104_Skin_Post3rd_freq                             barcodes sctcr_category
1             0.04638219 P104_Skin_Post3rd_ATGTGTGTCCTTTACA-1        Post3rd
2             0.04638219 P104_Skin_Post3rd_GCATGATCAGCTCGCA-1        Post3rd
3             0.04638219 P104_Skin_Post3rd_GTATTCTCAGTATCTG-1        Post3rd
  sctcr_category2 sctcr_category3 reactive
1        Reactive        Reactive     TRUE
2        Reactive        Reactive     TRUE
3        Reactive        Reactive     TRUE
p108_skin_freq %>%
  filter(reactive == TRUE)
                             beta
1 TRBV20-1.TRBJ2-1;CSAETGDYYNEQFF
                                                         vjaa
1 TRAV3.TRAJ34;CAVRDILNTDKLIF_TRBV20-1.TRBJ2-1;CSAETGDYYNEQFF
  P108_Skin_Pre3rd_count P108_Skin_Pre3rd_freq P108_Skin_Post3rd_count
1                      0                     0                       1
  P108_Skin_Post3rd_freq                             barcodes sctcr_category
1             0.07331378 P108_Skin_Post3rd_GGTATTGCATCATCCC-1        Post3rd
  sctcr_category2 sctcr_category3 reactive
1        Reactive        Reactive     TRUE

3.6 Save scTCR frequencies

# Save TILs
write.csv(p101_tils_freq, "sctcr_scRep_p101_til_freq_Part2.csv", row.names = FALSE)
write.csv(p103_tils_freq, "sctcr_scRep_p103_til_freq_Part2.csv", row.names = FALSE)
write.csv(p104_tils_freq, "sctcr_scRep_p104_til_freq_Part2.csv", row.names = FALSE)
write.csv(p108_tils_freq, "sctcr_scRep_p108_til_freq_Part2.csv", row.names = FALSE)

# Save skin
write.csv(p101_skin_freq, "sctcr_scRep_p101_skin_freq_Part2.csv", row.names = FALSE)
write.csv(p103_skin_freq, "sctcr_scRep_p103_skin_freq_Part2.csv", row.names = FALSE)
write.csv(p104_skin_freq, "sctcr_scRep_p104_skin_freq_Part2.csv", row.names = FALSE)
write.csv(p105_skin_freq, "sctcr_scRep_p105_skin_freq_Part2.csv", row.names = FALSE)
write.csv(p106_skin_freq, "sctcr_scRep_p106_skin_freq_Part2.csv", row.names = FALSE)
write.csv(p108_skin_freq, "sctcr_scRep_p108_skin_freq_Part2.csv", row.names = FALSE)
write.csv(p109_skin_freq, "sctcr_scRep_p109_skin_freq_Part2.csv", row.names = FALSE)
write.csv(p110_skin_freq, "sctcr_scRep_p110_skin_freq_Part2.csv", row.names = FALSE)
write.csv(p111_skin_freq, "sctcr_scRep_p111_skin_freq_Part2.csv", row.names = FALSE)

3.7 Get session info

sessionInfo()
R version 4.3.2 (2023-10-31)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Rocky Linux 8.10 (Green Obsidian)

Matrix products: default
BLAS/LAPACK: /usr/lib64/libopenblasp-r0.3.15.so;  LAPACK version 3.9.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

time zone: America/New_York
tzcode source: system (glibc)

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] scRepertoire_2.0.0 Seurat_5.1.0       SeuratObject_5.0.2 sp_2.2-0          
 [5] lubridate_1.9.4    forcats_1.0.0      stringr_1.5.1      dplyr_1.1.4       
 [9] purrr_1.0.4        readr_2.1.5        tidyr_1.3.1        tibble_3.2.1      
[13] ggplot2_3.5.1      tidyverse_2.0.0   

loaded via a namespace (and not attached):
  [1] cubature_2.1.1              RcppAnnoy_0.0.22           
  [3] splines_4.3.2               later_1.4.1                
  [5] bitops_1.0-9                polyclip_1.10-7            
  [7] fastDummies_1.7.5           lifecycle_1.0.4            
  [9] globals_0.16.3              lattice_0.22-7             
 [11] MASS_7.3-60.0.1             magrittr_2.0.3             
 [13] plotly_4.10.4               rmarkdown_2.29             
 [15] httpuv_1.6.15               sctransform_0.4.1          
 [17] spam_2.11-1                 spatstat.sparse_3.1-0      
 [19] reticulate_1.42.0           cowplot_1.1.3              
 [21] pbapply_1.7-2               RColorBrewer_1.1-3         
 [23] abind_1.4-8                 zlibbioc_1.48.2            
 [25] Rtsne_0.17                  GenomicRanges_1.54.1       
 [27] ggraph_2.2.1                BiocGenerics_0.48.1        
 [29] RCurl_1.98-1.17             tweenr_2.0.3               
 [31] evmix_2.12                  GenomeInfoDbData_1.2.11    
 [33] IRanges_2.36.0              S4Vectors_0.40.2           
 [35] ggrepel_0.9.5               irlba_2.3.5.1              
 [37] listenv_0.9.1               spatstat.utils_3.1-0       
 [39] iNEXT_3.0.1                 MatrixModels_0.5-3         
 [41] goftest_1.2-3               RSpectra_0.16-2            
 [43] spatstat.random_3.3-1       fitdistrplus_1.2-2         
 [45] parallelly_1.41.0           leiden_0.4.3.1             
 [47] codetools_0.2-20            DelayedArray_0.28.0        
 [49] ggforce_0.4.2               tidyselect_1.2.1           
 [51] farver_2.1.2                viridis_0.6.5              
 [53] matrixStats_1.5.0           stats4_4.3.2               
 [55] spatstat.explore_3.3-2      jsonlite_1.8.9             
 [57] tidygraph_1.3.1             progressr_0.15.1           
 [59] ggridges_0.5.6              ggalluvial_0.12.5          
 [61] survival_3.8-3              tools_4.3.2                
 [63] stringdist_0.9.12           ica_1.0-3                  
 [65] Rcpp_1.0.14                 glue_1.8.0                 
 [67] gridExtra_2.3               SparseArray_1.2.4          
 [69] xfun_0.50                   MatrixGenerics_1.14.0      
 [71] GenomeInfoDb_1.38.8         withr_3.0.2                
 [73] fastmap_1.2.0               SparseM_1.84-2             
 [75] digest_0.6.37               timechange_0.3.0           
 [77] R6_2.6.1                    mime_0.13                  
 [79] colorspace_2.1-1            scattermore_1.2            
 [81] tensor_1.5                  spatstat.data_3.1-2        
 [83] generics_0.1.3              data.table_1.15.4          
 [85] graphlayouts_1.1.1          httr_1.4.7                 
 [87] htmlwidgets_1.6.4           S4Arrays_1.2.1             
 [89] uwot_0.2.3                  pkgconfig_2.0.3            
 [91] gtable_0.3.6                lmtest_0.9-40              
 [93] SingleCellExperiment_1.24.0 XVector_0.42.0             
 [95] htmltools_0.5.8.1           dotCall64_1.2              
 [97] scales_1.3.0                Biobase_2.62.0             
 [99] png_0.1-8                   spatstat.univar_3.0-0      
[101] ggdendro_0.2.0              knitr_1.49                 
[103] rstudioapi_0.17.1           rjson_0.2.23               
[105] tzdb_0.5.0                  reshape2_1.4.4             
[107] nlme_3.1-168                zoo_1.8-13                 
[109] cachem_1.1.0                KernSmooth_2.23-26         
[111] parallel_4.3.2              miniUI_0.1.1.1             
[113] pillar_1.10.1               grid_4.3.2                 
[115] vctrs_0.6.5                 RANN_2.6.2                 
[117] VGAM_1.1-13                 promises_1.3.2             
[119] xtable_1.8-4                cluster_2.1.8.1            
[121] evaluate_1.0.1              truncdist_1.0-2            
[123] cli_3.6.3                   compiler_4.3.2             
[125] rlang_1.1.5                 crayon_1.5.3               
[127] future.apply_1.11.3         plyr_1.8.9                 
[129] stringi_1.8.4               viridisLite_0.4.2          
[131] deldir_2.0-4                munsell_0.5.1              
[133] gsl_2.1-8                   lazyeval_0.2.2             
[135] spatstat.geom_3.3-2         quantreg_6.1               
[137] Matrix_1.6-5                RcppHNSW_0.6.0             
[139] hms_1.1.3                   patchwork_1.3.0            
[141] future_1.34.0               shiny_1.9.1                
[143] SummarizedExperiment_1.32.0 evd_2.3-7.1                
[145] ROCR_1.0-11                 igraph_2.0.3               
[147] memoise_2.0.1